package com.example.proyectofc;

import java.util.ArrayList;

public class Dtw{
//	protected ArrayList<Coordenada> seq1 = new ArrayList<Coordenada>();
//	protected ArrayList<Coordenada> seq2 = new ArrayList<Coordenada>();
	protected double[][] caminoAlinea;

	protected int n;
	protected int m;
	protected int K;
	
	protected double distanciaAlinea;

	public Dtw(ArrayList<Double> patron, ArrayList<Double> ejemplo) {
//		seq1 = sample;
//		seq2 = templete;

		n = patron.size();       
		m = ejemplo.size();
		K = 1;
		
		caminoAlinea = new double[n + m][2];        // max(n, m) <= K < n + m
		distanciaAlinea = 0.0;

		this.compute(patron, ejemplo);
	}
       
	public void compute(ArrayList<Double> patron, 
			ArrayList<Double> ejemplo) {
		double distanciaAcumulada = 0.0;

		double[][] d = new double[n][m];        // local distances
		double[][] D = new double[n][m];        // global distances

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				d[i][j] = distanciaEntreDosPuntos(patron.get(i), 
						ejemplo.get(j));
			}
		}
		D[0][0] = d[0][0];
		
		for (int i = 1; i < n; i++) {
			D[i][0] = d[i][0] + D[i - 1][0];
		}
		for (int j = 1; j < m; j++) {
			D[0][j] = d[0][j] + D[0][j - 1];
		}

		for (int i = 1; i < n; i++) {
			for (int j = 1; j < m; j++) {
				distanciaAcumulada = Math.min(Math.min(D[i-1][j], D[i-1][j-1])
						, D[i][j-1]);
				distanciaAcumulada += d[i][j];
				D[i][j] = distanciaAcumulada;
			}
		}
		distanciaAcumulada = D[n - 1][m - 1];

		int i = n - 1;
		int j = m - 1;
		int minIndex = 1;

		caminoAlinea[K - 1][0] = i;
		caminoAlinea[K - 1][1] = j;
		
		while ((i + j) != 0) {
			if (i == 0) {
				j -= 1;
			} else if (j == 0) {
				i -= 1;
			} else {        // i != 0 && j != 0
				double[] array = { D[i - 1][j], D[i][j - 1], D[i - 1][j - 1] };
				minIndex = this.getIndiceMinimo(array);
					
				if (minIndex == 0) {
					i -= 1;
				} else if (minIndex == 1) {
					j -= 1;
				} else if (minIndex == 2) {
					i -= 1;
					j -= 1;
				}
			} // end else
			K++;
			caminoAlinea[K - 1][0] = i;
			caminoAlinea[K - 1][1] = j;
		} // end while
//		
		distanciaAlinea = distanciaAcumulada / K;

//		this.reversePath(warpingPath);
	}

//	protected void invertirCamino(double[][] path) {
//		double[][] nuevoCamino = new double[K][2];
//		for (int i = 0; i < K; i++) {
//			for (int j = 0; j < 2; j++) {
//				nuevoCamino[i][j] = path[K - i - 1][j];
//			}
//		}
//		caminoAlinea = nuevoCamino;
//	}


	public double getDistancia() {
		return distanciaAlinea;
	}

	protected double distanciaEntreDosPuntos(Double p1, Double p2) {
		return Math.sqrt( Math.pow((p1 - p2), 2));
//				+ Math.pow((p1.getY() - p2.getY()), 2)
//				+ Math.pow((p1.getZ() - p2.getZ()), 2));
	}

	protected int getIndiceMinimo(double[] array) {
		int indice = 0;
		double val = array[0];

		for (int i = 1; i < array.length; i++) {
			if (array[i] < val) {
				val = array[i];
				indice = i;
			}
		}
		return indice;
	}
}
